"""
面向对象技术简介

类(Class): 用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。对象是类的实例。
类变量：类变量在整个实例化的对象中是公用的。类变量定义在类中且在函数体之外。类变量通常不作为实例变量使用。
数据成员：类变量或者实例变量用于处理类及其实例对象的相关的数据。
方法重写：如果从父类继承的方法不能满足子类的需求，可以对其进行改写，这个过程叫方法的覆盖（override），也称为方法的重写。
实例变量：定义在方法中的变量，只作用于当前实例的类。
继承：即一个派生类（derived class）继承基类（base class）的字段和方法。继承也允许把一个派生类的对象作为一个基类对象对待。例如，有这样一个设计：一个Dog类型的对象派生自Animal类，这是模拟"是一个（is-a）"关系（例图，Dog是一个Animal）。
实例化：创建一个类的实例，类的具体对象。
方法：类中定义的函数。
对象：通过类定义的数据结构实例。对象包括两个数据成员（类变量和实例变量）和方法。

Python中的类提供了面向对象编程的所有基本功能：类的继承机制允许多个基类，派生类可以覆盖基类中的任何方法，方法中可以调用基类中的同名方法。
对象可以包含任意数量和类型的数据。
"""

"""
类定义：
    class ClassName:
        <statement-1>
        .
        .
        .
        <statement-N>
"""


class Human:
    def speak(self):
        print("Hahah")


class Person:
    name = ""

    def speak(self):
        print("Hahah ,my name is '%s'" % self.name)

    # 构造方法
    # 类定义中的self代表实例，而非类
    # 类的方法与普通的函数只有一个特别的区别——它们必须有一个额外的第一个参数名称, 按照惯例它的名称是 self。

    def __init__(self, name=''):
        self.name = name

    # self 不是 python 关键字，我们把他换成 this 也是可以正常执行的
    def setName(this, name):
        this.name = name

    def getName(self):
        return self.name


person = Person('LZH')
print("The name of the persion is '%s'." % person.name)
person.setName('lzh')
print("The name of the persion is '%s'." % person.getName())

"""
继承:继承是面向对象的基本特征，python支持多继承
需要注意圆括号中父类的顺序，若是父类中有相同的方法名，而在子类使用时未指定，python从左至右搜索 即方法在子类中未找到时，从左到右查找父类中是否包含方法。
类定义：
    class ChildClass(package.module.ParentClass1, package.module.ParentClass2, package.module.ParentClass3):
        <statement-1>
        .
        .
        .
        <statement-N>
"""


class Doctor(Person, Human):
    # __private_attrs：两个下划线开头，声明该属性为私有，不能在类地外部被使用或直接访问。在类内部的方法中使用时 self.__private_attrs
    __position = ''

    # __private_method：两个下划线开头，声明该方法为私有方法，只能在类的内部调用 ，不能在类地外部调用
    def __changeName(self):
        return "Mr. " + self.name

    def __init__(self, name, position):
        # 调用父类的方法
        Person.__init__(self, name)
        self.__position = position

    def getPosition(self):
        return self.__position

    def setPosition(self, position):
        self.__position = position

    def __del__(self):
        print("%s die!" % self.__changeName())


doctor = Doctor('Lzh', 'assistant')
print("%s's position is %s" % (doctor.getName(), doctor.getPosition()))
doctor.setPosition('director')
print("%s's position is %s" % (doctor.getName(), doctor.getPosition()))
doctor.speak()

"""
运算符重载
基于类的专有方法：
    __init__ : 构造函数，在生成对象时调用
    __del__ : 析构函数，释放对象时使用
    __repr__ : 打印，转换
    __setitem__ : 按照索引赋值
    __getitem__: 按照索引获取值
    __len__: 获得长度
    __cmp__: 比较运算
    __call__: 函数调用
    __add__: 加运算
    __sub__: 减运算
    __mul__: 乘运算
    __div__: 除运算
    __mod__: 求余运算
    __pow__: 乘方
"""


class Vector:
    def __init__(self, a, b):
        self.a = a
        self.b = b

    def __str__(self):
        return 'Vector (%d, %d)' % (self.a, self.b)

    def __add__(self, other):
        return Vector(self.a + other.a, self.b + other.b)


v1 = Vector(2, 10)
v2 = Vector(5, -2)
print(v1 + v2)
